# 1、useContext
以前我们获取 Context 数据时,有两种方式:
类组件中
import { ThemeContext } from './context/index.js'
// 方式1
class Soners extends React.Component {
//
render() {
const { theme } = this.context
return <Button style={{ ...theme }} />
}
}
Soners.contextType = ThemeContext
import { ThemeContext } from './context/index.js'
// 方式2✨(多用于Context嵌套中)
class Soners extends React.Component {
//
render() {
return (
<ThemeContext.Consumer>
{(value) => {
return <Button style={{ ...value }} />
}}
</ThemeContext.Consumer>
)
}
}
但是依然繁琐,使用 hook 的话就变得简单的多:
import { ThemeContext } from './context/index.js'
import { useContext } from 'react'
function Soners(props) {
const theme = useContext(ThemeContext)
return (
<div>
<p style={{ color: theme.color, fontSize: theme.size }}>
现在不是去想缺少什么的时候,该想一想凭现有的东西你能做什么。
</p>
</div>
)
}
# 2、useCallback
简单语句话:
useCallback(fn, deps)
相当于useMemo(() => fn, deps)
。
但不同的是,它是将内联回调函数及依赖项数组作为参数传入 useCallback
其主要的应用是:
应用 1:跳过组件的重新渲染
将函数传递给子组件时使用 useCallback,优点解析:
尽管父组件中待传普通函数状态没有发生变化,但当父组件中其他 state 发生变化时,父组件依然会重新渲染;如果子组件本身较为复杂的话,这个性能损失是非常大的。
- 父组件
import { useCallback } from 'react'
function father(props) {
let [msg, setMsg] = useState(0)
let [count, setCount] = useState(1)
let countChange = useCallback(() => {
setCount(count + 1)
}, [count])
// function countChange() {
// setCount(count + 1)
// }
return (
<div>
<p>计数:{count}</p>
<button onClick={countChange}>count值 +1</button>
<Son countChange={countChange} />
<button onClick={setMsg(Math.random())}>改变其他state状态</button>
</div>
)
}
// 使用 memo
export default memo(Demo)
- 子组件
function son(props) {
// 数组解构
let { countChange } = props
return (
<div>
<button onClick={countChange}>count值 +1</button>
</div>
)
}
// 使用 memo
export default memo(Demo)
# 3、useRef
useRef 在 react 中,大致有两个作用:
# ① 保存数据
此时 useRef 和 useState 类似,但也有更多不同 (opens new window):
如果你的组件需要存储一些值,但不影响渲染逻辑,请选择 useRef
简单的说 useRef 的值变量,不会触发渲染。而 useState 的值需要使用 setXxxx(),因此会触发页面渲染
对 useCallback 案例进行优化
- 父组件
import { useCallback } from 'react'
function father(props) {
let [msg, setMsg] = useState(0)
let [count, setCount] = useState(1)
let countRef = useRef()
countRef.current = count
let countChange = useCallback(() => {
setCount(countRef.current + 1)
}, [])
return (
<div>
<p>计数:{count}</p>
<button onClick={countChange}>count值 +1</button>
<Son countChange={countChange} />
<button onClick={setMsg(Math.random())}>改变其他state状态</button>
</div>
)
}
// 使用 memo
export default memo(Demo)
import { useRef } from 'react'
export default function Counter() {
let countRef = useRef(0)
function handleClick() {
// 这样并未重新渲染组件!
countRef.current = countRef.current + 1
// alert('You clicked ' + ref.current + ' times!');
}
return <button onClick={handleClick}>你点击了 {countRef.current} 次</button>
}
# ② 获取 DOM
如果 useRef 作为获取 DOm 的作用的话,其使用和 在类组件中的 createRef() 类似:
类组件中
class Demo extends React.Component {
constructor() {
this.bookSelectRef = React.createRef()
}
getNativeDom() {
console.log(this.bookSelect.current)
}
render() {
return (
<div>
<p ref={this.bookSelectRef}>JavaScript高级程序设计</p>
<p>你不知道的js</p>
<button onClick={(e) => this.getNativeDom()}>获取DOM</button>
</div>
)
}
}
import { useRef } from 'react'
function Demo(props) {
const bookSelectRef = useRef(null)
function getNativeDom() {
console.log(bookSelectRef.current)
}
return (
<div>
<p ref={bookSelectRef}>JavaScript高级程序设计</p>
<p>你不知道的js</p>
<button onClick={getNativeDom}>获取DOM</button>
</div>
)
}
# 4、useMemo
与 useCallback 非常相似,两者的区别如下:
// 使用useCallback
let fn = useCallback(() => {
//
// ……
}, [])
// 使用useMemo
let result = useMemo(() => {
//
return fn()
}, [])
# 5、useReducer
useReducer 可以对一些 state 处理必须复杂的逻辑进行拆分。
useReducer (opens new window) --> 其实现的思想和 redux 极度相似
// const initialState = { count: 0 }
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
default:
throw new Error()
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 })
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
</>
)
}